﻿using System;
using System.Reflection;
using System.Threading.Tasks;

#nullable disable
namespace BeetleX.XRPC.Clients
{
  public class ClientActionHandler
  {
    private Type mCompletionSourceType;

    public ClientActionHandler(MethodInfo method)
    {
      this.MethodInfo = method;
      this.MethodHandler = new MethodHandler(method);
      this.ResultType = method.ReturnType;
      PropertyInfo property = method.ReturnType.GetProperty("Result", BindingFlags.Instance | BindingFlags.Public);
      if (property != (PropertyInfo) null)
      {
        this.ResultProperty = new PropertyHandler(property);
        this.ResultPropertyInfo = property;
      }
      this.IsTaskResult = this.ResultType.BaseType == typeof (Task) || this.ResultType == typeof (Task);
      this.IsVoid = this.ResultType == typeof (void);
      this.ResponseType = this.GetResponseType();
    }

    public bool IsTaskResult { get; private set; }

    public bool IsVoid { get; private set; }

    public string Url { get; set; }

    public MethodInfo MethodInfo { get; set; }

    public PropertyInfo ResultPropertyInfo { get; set; }

    internal MethodHandler MethodHandler { get; set; }

    public Type ResultType { get; set; }

    internal PropertyHandler ResultProperty { get; set; }

    public Type[] ResponseType { get; set; }

    private Type[] GetResponseType()
    {
      if (this.IsVoid)
        return new Type[0];
      if (this.IsTaskResult)
      {
        if (this.ResultProperty == null)
          return new Type[0];
        return new Type[1]
        {
          this.ResultProperty.Property.PropertyType
        };
      }
      return new Type[1]{ this.ResultType };
    }

    public object Execute(object controller, params object[] parameters)
    {
      return this.MethodHandler.Execute(controller, parameters);
    }

    internal IAnyCompletionSource GetCompletionSource()
    {
      if (this.mCompletionSourceType == (Type) null)
      {
        Type type = typeof (AnyCompletionSource<>);
        if (this.ResultProperty != null)
          this.mCompletionSourceType = type.MakeGenericType(this.ResultProperty.Property.PropertyType);
        else
          this.mCompletionSourceType = type.MakeGenericType(typeof (object));
      }
      return (IAnyCompletionSource) Activator.CreateInstance(this.mCompletionSourceType);
    }
  }
}
